const { DataTypes, Op } = require('sequelize');
const bcrypt = require('bcryptjs');
const sequelize = require('../config/database');

const User = sequelize.define('User', {
  id: {
    type: DataTypes.UUID,
    defaultValue: DataTypes.UUIDV4,
    primaryKey: true
  },
  username: {
    type: DataTypes.STRING,
    allowNull: false,
    validate: {
      len: [3, 30],
      is: /^[a-zA-Z0-9_-]+$/
    },
    comment: '用户名'
  },
  email: {
    type: DataTypes.STRING,
    allowNull: false,
    validate: {
      isEmail: true
    },
    comment: '邮箱'
  },
  password: {
    type: DataTypes.STRING,
    allowNull: false,
    validate: {
      len: [8, 100],
      isStrongPassword(value) {
        if (!/(?=.*[a-z])/.test(value)) {
          throw new Error('密码必须包含小写字母');
        }
        if (!/(?=.*[A-Z])/.test(value)) {
          throw new Error('密码必须包含大写字母');
        }
        if (!/(?=.*\d)/.test(value)) {
          throw new Error('密码必须包含数字');
        }
        if (!/(?=.*[!@#$%^&*])/.test(value)) {
          throw new Error('密码必须包含特殊字符');
        }
      }
    },
    comment: '密码'
  },
  phone_number: {
    type: DataTypes.STRING,
    validate: {
      is: {
        args: /^1[3-9]\d{9}$/,
        msg: '请输入有效的中国大陆手机号码'
      }
    },
    comment: '手机号'
  },
  wechat_open_id: {
    type: DataTypes.STRING,
    comment: '微信开放ID'
  },
  wechat_union_id: {
    type: DataTypes.STRING,
    comment: '微信联合ID'
  },
  role: {
    type: DataTypes.ENUM('admin', 'staff', 'student', 'user'),
    defaultValue: 'user',
    comment: '用户角色'
  },
  status: {
    type: DataTypes.ENUM('active', 'inactive', 'suspended'),
    defaultValue: 'active',
    comment: '用户状态'
  },
  points: {
    type: DataTypes.INTEGER,
    defaultValue: 0,
    validate: {
      min: 0
    },
    comment: '积分'
  },
  member_level: {
    type: DataTypes.INTEGER,
    defaultValue: 1,
    validate: {
      min: 1
    },
    comment: '会员等级'
  },
  last_login_at: {
    type: DataTypes.DATE,
    comment: '上次登录时间'
  },
  last_active_at: {
    type: DataTypes.DATE,
    comment: '上次活跃时间'
  },
  last_login_platform: {
    type: DataTypes.ENUM('web', 'app', 'wechat'),
    defaultValue: 'web',
    comment: '上次登录平台'
  },
  is_active: {
    type: DataTypes.BOOLEAN,
    defaultValue: true,
    comment: '是否活跃'
  },
  login_attempts: {
    type: DataTypes.INTEGER,
    defaultValue: 0,
    comment: '登录尝试次数'
  },
  locked_until: {
    type: DataTypes.DATE,
    comment: '锁定时间'
  }
}, {
  hooks: {
    beforeSave: async (user) => {
      if (user.changed('password')) {
        const salt = await bcrypt.genSalt(12);
        user.password = await bcrypt.hash(user.password, salt);
      }
    }
  },
  defaultScope: {
    attributes: { exclude: ['password', 'login_attempts', 'locked_until'] },
    comment: '默认查询范围'
  },
  scopes: {
    withPassword: {
      attributes: {},
      comment: '包含密码的查询范围'
    }
  },
  indexes: [
    {
      unique: true,
      fields: ['username'],
      name: 'user_username_unique',
      comment: '用户名索引'
    },
    {
      unique: true,
      fields: ['email'],
      name: 'user_email_unique',
      comment: '邮箱索引'
    },
    {
      unique: true,
      fields: ['phone_number'],
      where: {
        phone_number: {
          [Op.ne]: null
        }
      },
      name: 'user_phone_unique',
      comment: '手机号索引'
    },
    {
      unique: true,
      fields: ['wechat_open_id'],
      where: {
        wechat_open_id: {
          [Op.ne]: null
        }
      },
      name: 'user_wechat_open_unique',
      comment: '微信开放ID索引'
    },
    {
      unique: true,
      fields: ['wechat_union_id'],
      where: {
        wechat_union_id: {
          [Op.ne]: null
        }
      },
      name: 'user_wechat_union_unique',
      comment: '微信联合ID索引'
    },
    {
      fields: ['status', 'role'],
      name: 'user_status_role',
      comment: '状态和角色索引'
    }
  ],
  comment: '用户信息表'
});

// Instance method to check password
User.prototype.validatePassword = async function(password) {
  return await bcrypt.compare(password, this.password);
};

// Instance method to hash password
User.prototype.hashPassword = async function(password) {
  const salt = await bcrypt.genSalt(12);
  return await bcrypt.hash(password, salt);
};

module.exports = User; 